from __future__ import absolute_import

import binascii
import io

import apkutils
import pyftype
from apkutils import apkfile
from apkutils.apk import APK
from xscanner.modules import *


class ApkData(Data):
    def __init__(self):
        self._type = "apk"
        self._mime = "application/vnd.android.package-archive"

    def from_bytes(self, _bytes):
        super(ApkData, self).from_bytes(_bytes)

        self.zfile = apkfile.ZipFile(io.BytesIO(_bytes), "r")
        self._init_zipfiles()

        self.apk = APK.from_bytes(_bytes)
    
    def close(self):
        self.apk.close()

    def _init_zipfiles(self):
        self._sub_files = {}
        self._strings = {}
        self._hexs = {}
        for name in self.zfile.namelist():
            bs = self.zfile.read(name)
            self._sub_files[name] = bs
            self._strings[name] = bs.decode("utf-8", errors="ignore")
            self._hexs[name] = binascii.hexlify(bs).decode("ascii")
        self.zfile.close()

    def match_app_name(self, name):
        pass

    def match_manifest(self, s, flag):
        if flag == MODE_STRING_REGEX:
            return re.search(s, self.apk.get_manifest()) is not None
        return s in self.apk.get_manifest()

    def match_manifest_activity(self, activity):
        return activity in self.apk.get_manifest_activities()

    def match_manifest_receiver(self, receiver):
        return receiver in self.apk.get_manifest_receivers()

    def match_manifest_service(self, service):
        return service in self.apk.get_manifest_services()

    def match_manifest_provider(self, provider):
        return provider in self.apk.get_manifest_providers()

    def match_manifest_action(self, action):
        return action in self.apk.get_manifest_actions()

    def match_manifest_permission(self, permission):
        return permission in self.apk.get_manifest_permissions()

    def match_certificate_md5(self, certificate_md5):
        pass

    def match_certificate_sha1(self, certificate_sha1):
        pass

    def match_certificate_sha256(self, certificate_sha256):
        pass

    def match_certificate_issue(self, certificate_issue):
        pass

    def match_certificate_subject(self, certificate_subject):
        pass
    
    def get_activities_num(self):
        return self.apk.get_activities_num()

    def get_receivers_num(self):
        return self.apk.get_receivers_num()

    def get_services_num(self):
        return self.apk.get_services_num()

    def get_providers_num(self):
        return self.apk.get_providers_num()

    def get_permission_num(self):
        return self.apk.get_permission_num()

    def get_min_sdk(self):
        pass
    
    def get_max_sdk(self):
        pass

    def get_target_sdk(self):
        pass

    def get_manifest_main_activities(self):
        return self.apk.get_manifest_main_activities()
    
    def get_manifest_applications(self):
        return self.apk.get_manifest_application()
    
    def match_dex_class(self, clz):
        if clz is None:
            return False
        return clz.encode() in self.apk.get_dex_classes()

    def match_dex_string(self, s, flag):
        if flag == MODE_STRING:
            s = s.encode('utf-8')
            for item in self.apk.get_dex_strings():
                if s in item:
                    return True
        elif flag == MODE_STRING_REGEX:
            p = re.compile(s.encode('utf-8'))
            for item in self.apk.get_dex_strings():
                if p.search(item) is not None:
                    return True
        elif flag == MODE_HEX:
            for item in self.apk.get_dex_hex_strings():
                # if len(s) == len(item):
                #     print(s, item)
                if s in item:
                    return True
        elif flag == MODE_HEX_REGEX:
            p = re.compile(s)
            for item in self.apk.get_dex_hex_strings():
                if p.search(item) is not None:
                    return True
        return False

    def match_dex_method_string(self, mtd, s):
        # 指定方法内，出现指定字符串
        pass

    def match_url(self, url):
        pass
    
    def match_dex_hex(self, hexs):
        """匹配dex中某段硬编码的数据

        :param hexs: [description]
        :type hexs: [type]
        """
        pass
    
    # def match_file_name(self, file_name, mode):
    #     if mode == MODE_STRING:
    #         for name in self._strings.keys():
    #             if file_name in name:
    #                 return True
        
    #     if mode == MODE_STRING_REGEX:
    #         p = re.compile(file_name)
    #         for name in self._strings.keys():
    #             if p.search(name) is not None:
    #                 return True
    #     return False

    def match_subfile(self, name, nflag, content, cflag):
        for k in self._strings.keys():
            if nflag == MODE_STRING:
                if name not in k:
                    continue
            elif nflag == MODE_STRING_REGEX:
                if re.search(name, k) is None:
                    continue
            
            if cflag == MODE_STRING:
                if content in self._strings[k]:
                    return True
            elif cflag == MODE_STRING_REGEX:
                if re.search(content, self._strings[k]) is not None:
                    return True
            elif cflag == MODE_HEX:
                return content in self._hexs[k]
            elif cflag == MODE_HEX_REGEX:
                if re.search(content, self._hexs[k]) is not None:
                    return True

        return False
